home *** CD-ROM | disk | FTP | other *** search
/ Business Shareware / Business Shareware.iso / start / edu / romancvt / rom2arab.c < prev    next >
C/C++ Source or Header  |  1993-04-14  |  3KB  |  149 lines

  1. /* rom2arab.c
  2.  
  3.    David S McMeans   Not copyrighted April 1993
  4.    mcmeans@dtedi.hq.aflc.af.mil
  5.  
  6. Roman2Arabic()
  7. Converts a Roman number to its Arabic equivalent.
  8.  
  9. Call
  10.  
  11. int Roman2Arabic( str )
  12. char *str;           roman number to be converted
  13.  
  14. Returns
  15.  
  16. INT         
  17.  
  18. Description
  19.  
  20. Roman2Arabic() does no error checking.  Invalid Roman numerals are ignored.
  21.  
  22. Notes
  23.  
  24. Roman2Arabic_() does rudimentary error checking.  If the Roman number is
  25. receives is invalid, it returns 0.
  26.  
  27. This information was compiled from a discussion in comp.lang.pascal around
  28. March 1993.  Acknowledgements go to Bengt Oehman (d92bo@efd.lth.se), and to
  29. David Conrad (dave@tygra.michigan.com).
  30.  
  31. */
  32.  
  33.  
  34. #include "tailor.h"
  35.  
  36. #include <stdio.h>
  37. #include <stdlib.h>
  38. #include <string.h>
  39. #include <ctype.h>
  40.  
  41.  
  42. /*
  43.  *    PUBLIC DECLARATIONS
  44.  */
  45.  
  46. typedef enum bool {FALSE, TRUE} Boolean;
  47. typedef enum ret_t {ERROR=-1, SUCCESS} ReturnType;
  48.  
  49. extern  int Roman2Arabic    OF(( char * ));
  50. extern  int Roman2Arabic_   OF(( char * ));
  51.  
  52. /*
  53.  *    PRIVATE DECLARATIONS
  54.  */
  55.  
  56. static  int           roman_val    OF(( char ));
  57. static  Boolean       is_a_five    OF(( char ));
  58.  
  59. /* The following routine was provided by Dave Conrad */
  60.  
  61. int Roman2Arabic( str )
  62. char *str;
  63. {
  64.   int len, i, r, r_ahead, arab;
  65.  
  66.   arab = 0;
  67.   len = strlen( str );
  68.   for (i=0; i < len-1; i++)
  69.   {
  70.     r = roman_val( str[ i ] );
  71.     r_ahead = roman_val( str[ i+1 ] );
  72.     if (r < r_ahead)
  73.       arab -= r;
  74.     else
  75.       arab += r;
  76.   }
  77.   arab += roman_val( str[ len-1 ] );
  78.  
  79.   return arab;
  80. }
  81.  
  82. /* The following routine was provided by Bengt Oehman */
  83.  
  84. int Roman2Arabic_( str )
  85. char *str;
  86. {
  87.   int pos;
  88.   int value, curval, highestprev;
  89.  
  90.   highestprev = curval = value = 0;
  91.  
  92.   for (pos=strlen( str )-1; pos>-1; pos--)
  93.   {
  94.     if ((curval = roman_val( str[ pos ] ))==0)  /* invalid char in str */
  95.       return 0;
  96.     
  97.     if (curval >= highestprev)
  98.     {
  99.       value += curval;
  100.       highestprev = curval;
  101.     }
  102.     else /* numeral precedes one larger */
  103.     {
  104.       if (is_a_five( str[ pos ] ))  /* five may not precede anything larger */
  105.         return 0;
  106.  
  107.       if (highestprev / curval > 10) /* XM  IC  XD ... */
  108.         return 0;
  109.  
  110.       value -= curval;
  111.     }
  112.   }
  113.   return value;
  114. }
  115.  
  116. static int roman_val( n )
  117. char n;
  118. {
  119.   switch( toupper( n ) )
  120.   {
  121.     case 'I':
  122.       return 1;
  123.     case 'V':
  124.       return 5;
  125.     case 'X':
  126.       return 10;
  127.     case 'L':
  128.       return 50;
  129.     case 'C':
  130.       return 100;
  131.     case 'D':
  132.       return 500;
  133.     case 'M':
  134.       return 1000;
  135.     default:
  136.       return 0;
  137.   }
  138. }
  139.  
  140. static Boolean is_a_five( n )
  141. char n;
  142. {
  143.   char c=toupper( n );
  144.  
  145.   return (c=='V' || c=='L' || c=='D');
  146. }
  147.  
  148. /* end rom2arab.c */
  149.